package com.deer.wms.ware.task.web;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.deer.wms.intercept.annotation.User;
import com.deer.wms.intercept.common.data.CurrentUser;
import com.deer.wms.project.root.core.result.CommonCode;
import com.deer.wms.project.root.core.result.Result;
import com.deer.wms.project.root.core.result.ResultGenerator;
import com.deer.wms.project.root.exception.ServiceException;
import com.deer.wms.project.root.util.DateUtils;
import com.deer.wms.system.manage.model.user.UserInfo;
import com.deer.wms.system.manage.model.ware.WareInfo;
import com.deer.wms.system.manage.service.UserInfoService;
import com.deer.wms.ware.task.constant.WareTaskConstant;
import com.deer.wms.ware.task.model.SO.*;
import com.deer.wms.ware.task.model.Wave.*;
import com.deer.wms.ware.task.service.SoDetailService;
import com.deer.wms.ware.task.service.SoMasterService;
import com.deer.wms.ware.task.service.WaveDetailService;
import com.deer.wms.ware.task.service.WaveMasterService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import java.text.ParseException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 *
 * @author ll
 * @since 2020/02/02
 */
@RestController
@RequestMapping("/wave/masters")
public class WaveMasterController {

    @Autowired
    private WaveMasterService waveMasterService;
    @Autowired
    private WaveDetailService waveDetailService;
    @Autowired
    private SoMasterService soMasterService;
    @Autowired
    private SoDetailService soDetailService;

    @PostMapping
    public Result add(@RequestBody WaveMaster waveMaster) {
        waveMasterService.save(waveMaster);
        return ResultGenerator.genSuccessResult();
    }

    @GetMapping("/delete")
    public Result delete(Integer id) {
        waveDetailService.deleteByWaveMasterId(id);
        waveMasterService.removeById(id);
        return ResultGenerator.genSuccessResult();
    }

    @Autowired
    private UserInfoService userInfoService;

    @PostMapping("/update")
    public Result update(@RequestBody WaveMaster waveMaster) {
        UserInfo userInfo = userInfoService.getById(waveMaster.getAllotUserId());
        waveMaster.setAllotUserName(userInfo.getUserName());
        waveMaster.setAllotTime(DateUtils.getNowDateTimeString());
        waveMasterService.updateById(waveMaster);
        return ResultGenerator.genSuccessResult();
    }

    @GetMapping("/{id}")
    public Result detail(@PathVariable Integer id) {
        WaveMaster waveMaster = waveMasterService.getById(id);
        return ResultGenerator.genSuccessResult(waveMaster);
    }

    @GetMapping("/list")
    public Result list(WaveMasterCriteria criteria) {
        PageHelper.startPage(criteria.getPageNum(), criteria.getPageSize());
        List<WaveMasterDto> list = waveMasterService.findList(criteria);
        PageInfo pageInfo = new PageInfo(list);
        return ResultGenerator.genSuccessResult(pageInfo);
    }

    @GetMapping("/allotWave")
    public Result allotWave(WaveMasterCriteria criteria, @ApiIgnore @User CurrentUser currentUser) {
        PageHelper.startPage(criteria.getPageNum(), criteria.getPageSize());
        criteria.setUserId(currentUser.getUserId());
        List<WaveMasterDto> list = waveMasterService.allotWave(criteria);
        PageInfo pageInfo = new PageInfo(list);
        return ResultGenerator.genSuccessResult(pageInfo);
    }

    @GetMapping("/generateWaves")
    public Result generateWaves() {
        waveMasterService.generateWaves();
        return ResultGenerator.genSuccessResult();
    }

    @PostMapping("/transToWave")
    public Result transToWave(@RequestBody WaveDetailTransData waveDetailTransData) {
        WaveMaster wave = waveMasterService.getById(waveDetailTransData.getWaveId());
        for (Integer waveDetailId : waveDetailTransData.getWaveDetailIds()) {
            WaveDetail waveDetail = waveDetailService.getById(waveDetailId);
            waveDetail.setWaveMasterId(wave.getWaveId());
            waveDetailService.updateById(waveDetail);
        }
        return ResultGenerator.genSuccessResult();
    }

    @GetMapping("/allotPickUser")
    public Result allotPickUser(Integer waveMasterId, Integer userId, String userName) {
        WaveMaster wave = waveMasterService.getById(waveMasterId);
        wave.setAllotTime(DateUtils.getNowDateTimeString());
        wave.setAllotUserId(userId);
        wave.setAllotUserName(userName);
        waveMasterService.updateById(wave);
        return ResultGenerator.genSuccessResult();
    }



    @ApiOperation(value = "合并SO", notes = "生成波次（配料单）")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "access-token", value = "token", paramType = "header", dataType = "String", dataTypeClass = String.class, required = true)
    })
    @PostMapping("/merge")
    public Result merge(@RequestBody Merge merge, @ApiIgnore @User CurrentUser currentUser) {
        //Step1.取到待处理的数据
        List<SoDetail> soDetailList = soDetailService.list(new QueryWrapper<SoDetail>().in("bill_no", merge.getBillNos()));
        List<SoDetail> soDetails = soDetailList.stream().filter(soDetail -> soDetail.getOrderQuantity() > soDetail.getAllottedQuantity()).collect(Collectors.toList());
        if (CollectionUtil.isEmpty(soDetails)) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "不存在待分配的出库任务，请确认！");
        }
        Set<String> soBillNos = soDetails.stream().map(SoDetail::getBillNo).collect(Collectors.toSet());
        List<SoMaster> soMasterList = soMasterService.list(new QueryWrapper<SoMaster>().in("bill_no", soBillNos));

        //Step2.校验：是否是同一部门和同一任务单号
        List<SoMaster> collect = soMasterList.stream().filter(soMaster -> ObjectUtil.notEqual(soMaster.getState(), WareTaskConstant.OUT_STATE_INIT)).collect(Collectors.toList());
        if (collect.size() > 0) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "存在非新建状态的任务，不允许合并");
        }
//        Map<Integer, List<SoMaster>> soMap = soMasterList.stream().collect(Collectors.groupingBy(SoMaster::getDeptId));
//        if (soMap.size() > 1) {
//            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "存在多个部门的任务，不允许合并");
//        }

        //Step3.核心方法，合并
        waveMasterService.mergeSo(soMasterList, currentUser);
        return ResultGenerator.genSuccessResult();
    }

    @ApiOperation(value = "合并SO", notes = "生成波次（配料单）")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "access-token", value = "token", paramType = "header", dataType = "String", dataTypeClass = String.class, required = true)
    })
    @GetMapping("/cancel")
    public Result cancel(String waveCode) {
        WaveMaster waveMaster = waveMasterService.getOneByField("code", waveCode);
        waveMasterService.cancel(waveMaster);
        return ResultGenerator.genSuccessResult();
    }
}